<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
</head>
<body>
    <script>
        // 1、原型链继承

        function Person(){
            this.name = 'lzw';
            this.age = 21;
            this.score = [99];
            this.sayHi = function(){
                console.log(`我是${this.name}今年${this.age}了`)
            }
        }

        function Student(id){
            this.id = id
        }
        Student.prototype.sayEng = function(){
            console.log('eng')
        }
        Student.prototype = new Person();

        const stu = new Student('12');
        const stu2 = new Student('11');
        // stu.__proto__.name = 'zsw';
        stu.score.push(100);
        console.log(stu.__proto__===stu2.__proto__)


        // stu.sayEng() // 在继承之前添加到方法会丢失
        // console.log(stu.__proto__,stu2.__proto__)
        // stu.sayHi();
        
        // console.log(Student.prototype.constructor)  // 应该是Student 而不是Person

        // 弊端 1、多个实例对引用类型的操作会被篡改
        // 2、子类型上的constructor被重写了 被父类型覆盖了
        // 3、要在继承后在原型上添加方法
        // 4、 无法像父类型的构造函数传参


        // 2、构造函数继承 使用call bind apply

        // function Person(name){
        //     this.name = name;
        //     this.sayHi = function(){
        //         console.log(`我是${this.name}`)
        //     }
        //     this.getName = function(){
        //         return this.name;
        //     }
        // }

        // Person.prototype.sayHello = function(){
        //     console.log('hello');
        // }

        // function Student(name,age){
        //     Person.call(this,name);
        //     // Person.apply(this,[name]);
        //     // Person.bind(this,name)();
        //     this.age = age;
        // }

        // const stu= new Student('lzw',21);
        // stu.sayHi();
        // console.log(stu.getName());
        // 缺点 
        // stu.sayHello(); // 无法继承父类型原型上的方法和属性
        // 解决了引用的问题

        // 3、组合继承
        // function Person(name){
        //     this.name = name;
        //     this.arr = [1,2];
        //     this.sayName = function(){
        //         console.log(this.name)
        //     }
        // }

        // Person.prototype.sayHi = function(){
        //     console.log('hi')
        // }

        // function Student(name,score){
        //     Person.call(this,name);
        //     this.score = score;
        // }

        // Student.prototype = new Person();

        // const stu = new Student('1',1);
        // const stu2 = new Student('2',2);
        // stu.sayName();
        // stu.sayHi();
        // stu.arr.push(2);
        // console.log(stu,stu2);

        // 解决上述两类问题 但是构造函数会调用两次

        // 4、原型式继承
        // const person = {
        //     name:'lzw',
        //     sayHi:function(){
        //         console.log(this.name,'hi');
        //     }
        // }
        // function create(obj){
        //     function F (){};
        //     F.prototype = obj;
        //     return new F();
        // }

        // // const stu = Object.create(person);
        // const stu = create(person);
        // person.name = 'zsw'
        // stu.sayHi()

        // 缺点 1、无法实现复用
        // 2、拷贝引用如果继承的对象发生修改 新对象也会变化

        // 5、寄生式继承
        // const person = {
        //     name:'lzw',
        //     sayHi:function(){
        //         console.log(this.name,'hi');
        //     }
        // }

        // function clone(obj){
        //     const newObj = Object.create(obj);
        //     newObj.sayName = function(){
        //         console.log(this.name);
        //     }
        //     return newObj;
        // }

        // const stu = clone(person);
        // stu.sayName();
        // 在原型式继承的基础上 添加方法 但缺点依旧是无法复用

        // 6、寄生组合继承
        // function Person(name){
        //     this.name = name;
        //     this.sayHi = function(){
        //         console.log(this.age);
        //     }
        // }

        // Person.prototype.sayHello = function(){
        //     console.log('hello');
        // }

        // function Student(name,age){
        //     // 改变Preson中的this指向到Student
        //     Person.call(this,name);
        //     this.age = age;
        //     this.asyAge = function(){
        //         console.log(this.name);
        //     }
        // }

        // function clone(Father,Child){
        //     Child.prototype = Object.create(Father.prototype);
        //     Child.prototype.constrctor = Child;
        // }

        // clone(Person,Student);

        // const stu = new Student('lzw',21);
        // console.log(stu);
        // stu.sayHello();
        // stu.asyAge();

        // console.log(this)
    </script>
</body>
</html>